#include <pspkernel.h>
#define PSP_MODULE_MAX_NAME 28
#define PSP_LIB_MAX_NAME 128
#define PSP_ENTRY_MAX_NAME 128
#define PSP_MAX_V_ENTRIES 255
#define PSP_MAX_F_ENTRIES 65535

#define RT(op) ((op >> 16) & 0x1F)
#define RS(op) ((op >> 21) & 0x1F)
#define RD(op) ((op >> 11) & 0x1F)

enum PspEntryType {
	PSP_ENTRY_FUNC = 0,
	PSP_ENTRY_VAR = 1
};

typedef struct PspModuleInfo {
	u16 exec_mode;
	u8 revision;
	u8 version;
	char name[PSP_MODULE_MAX_NAME];
	u32 gp;
	u32 exports;
	u32 exp_end;
	u32 imports;
	u32 imp_end;
} PspModuleInfo;

typedef struct PspModuleImport {
	u32 name;
	u32 flags;
	u16 v_count; // ???
	u16 f_count;
	u32 nids;
	u32 funcs;
//	u32 vars;
} PspModuleImport;

typedef struct PspEntry {
//	char name[PSP_ENTRY_MAX_NAME];
	u32 nid;
	u32 addr;
} PspEntry;

typedef struct PspLibImport PspLibImport;
struct PspLibImport {
	/** Name of the library */
	char name[PSP_LIB_MAX_NAME];
	/** List of function entries */
	PspEntry* funcs;
	/** Number of function entries */
	int f_count;

//	PspEntry vars[PSP_MAX_V_ENTRIES];
//	int v_count;
};

typedef struct IsoModule {
	u8		used;
	SceUID	fd;
	int		file_offset;
	u32		exports;
	u32		exp_end;
	u32		imports;
	u32		imp_end;
	PspLibImport* libs;
	int		libs_count;
	int		mod_size;

	u16		attribute;
	u8		version;
	u8		revision;
	char	modname[27];
	SceUID	modid;
	u32		mpid_text;
	u32		mpid_data;
	u32		gp;
	u32		text_addr;
	u32		text_size;
	u32		entry_addr;
	u32		data_size;
} IsoModule;

int IsoModuleManagerInit();
IsoModule* IsoGetModuleByUID(SceUID modid);
u32 FindImport(IsoModule* module, const char* lib, u32 nid);

SceUID IsoLoadModule(const char* path);
int IsoStartModule(SceUID modid, int args, void* argp);
